//+------------------------------------------------------------------+
//|                                               Advanced forecater |
//| 断水流高级预测指标 - MT5版本 v2.2                                   |
//| 功能说明：基于修正MACD算法的高级趋势预测指标                           |
//| 主要特点：多时间框架支持、动态显示控制、精准趋势状态分析                |
//| 核心算法：修正MACD差值计算，提高趋势预测准确性                         |
//| 更新说明：修复核心计算逻辑，完善MT4到MT5的完全兼容转换                 |
//| 试用期限：30天                                                    |
//+------------------------------------------------------------------+
#property indicator_chart_window    // 指标显示在主图窗口
#property indicator_buffers 11      // 总缓冲区数量（11个缓冲区，与MT4一致）
#property indicator_plots   8       // 可视化绘图数量（8个：6条线+2个箭头）

#property indicator_label1  "Main Line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrMaroon
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

#property indicator_label2  "Up Line A"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrOrange
#property indicator_style2  STYLE_SOLID
#property indicator_width2  3

#property indicator_label3  "Up Line B"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrOrange
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2

#property indicator_label4  "Down Line A"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrLimeGreen
#property indicator_style4  STYLE_SOLID
#property indicator_width4  3

#property indicator_label5  "Down Line B"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrLimeGreen
#property indicator_style5  STYLE_SOLID
#property indicator_width5  3

#property indicator_label6  "Signal Line"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrMagenta
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1

#property indicator_label7  "Up Arrow"
#property indicator_type7   DRAW_ARROW
#property indicator_color7  clrOrange
#property indicator_style7  STYLE_SOLID
#property indicator_width7  2

#property indicator_label8  "Down Arrow"
#property indicator_type8   DRAW_ARROW
#property indicator_color8  clrLimeGreen
#property indicator_style8  STYLE_SOLID
#property indicator_width8  2

// 时间框架枚举定义 - 支持多时间框架分析
enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // 当前时间框架
   tf_m1  = PERIOD_M1,      // 1分钟
   tf_m5  = PERIOD_M5,      // 5分钟
   tf_m15 = PERIOD_M15,     // 15分钟
   tf_m30 = PERIOD_M30,     // 30分钟
   tf_h1  = PERIOD_H1,      // 1小时
   tf_h4  = PERIOD_H4,      // 4小时
   tf_d1  = PERIOD_D1,      // 日线
   tf_w1  = PERIOD_W1,      // 周线
   tf_mn1 = PERIOD_MN1,     // 月线
   tf_n1  = -1,             // 第一个更高时间框架
   tf_n2  = -2,             // 第二个更高时间框架
   tf_n3  = -3              // 第三个更高时间框架
};

// ===== 核心计算参数 =====
input enTimeFrames TimeFrame      = tf_cu;        // 时间框架选择：当前图表时间框架
input ENUM_APPLIED_PRICE Price    = PRICE_CLOSE;  // 价格类型：收盘价
input int             FastEma     = 13;           // 快速EMA周期：短期趋势指标
input int             SlowEma     = 34;           // 慢速EMA周期：长期趋势指标
input int             SignalMA    = 8;            // 信号移动平均周期：信号线计算
input ENUM_MA_METHOD  SignalMAMode = MODE_EMA;    // 信号MA类型：指数移动平均
input int             SigMA       = 8;            // 信号MA周期：辅助信号计算
input ENUM_MA_METHOD  SigMAMode   = MODE_EMA;     // 信号MA方法：指数移动平均

// ===== 警报系统设置 =====
input bool   alertsOn             = true;         // 启用警报功能：总开关
input bool   alertsOnCurrent      = false;        // 当前K线警报：是否在当前K线触发
input bool   alertsMessage        = true;         // 消息警报：弹窗提示
input bool   alertsSound          = false;        // 声音警报：音频提示
input bool   alertsEmail          = false;        // 邮件警报：邮件通知

// ===== 文本显示设置 =====
input bool   ShowText             = true;         // 显示文本：启用文本标签
input string TextDir              = "advanced forecaster Text"; // 文本对象前缀：标识符
input int    textCorner           = 1;            // 文本角落：显示位置角落
input int    textXPosition        = 10;           // 文本X坐标：水平位置
input int    textYPosition        = 10;           // 文本Y坐标：垂直位置
input color  upTextColor          = Blue;         // 上涨文本颜色：蓝色
input color  dnTextColor          = Red;          // 下跌文本颜色：红色
input int    upFontSize           = 12;           // 上涨字体大小：12像素
input int    dnFontSize           = 12;           // 下跌字体大小：12像素

// ===== 垂直线设置 =====
input bool   verticalLinesVisible = false;        // 垂直线可见：是否显示垂直线
input bool   linesOnFirst         = false;        // 首个K线显示：仅在第一个K线显示
input string verticalLinesID      = "advanced forecaster Lines"; // 垂直线ID：对象标识符
input color  verticalLinesUpColor = Blue;         // 上涨垂直线颜色：蓝色
input color  verticalLinesDnColor = Red;          // 下跌垂直线颜色：红色
input ENUM_LINE_STYLE verticalLinesStyle = STYLE_SOLID; // 垂直线样式：实线
input int    verticalLinesWidth   = 2;            // 垂直线宽度：2像素

// ===== 绘图选项 =====
input bool   Interpolate          = true;         // 插值计算：平滑处理
input bool   drawArrows           = false;        // 绘制箭头：信号箭头显示
input bool   ArrowsOnFirstBar     = false;        // 首K线箭头：仅在第一个K线显示箭头

// ===== 按钮控制设置 =====
input string             button_note1          = "------------------------------"; // 分隔线：界面美化
input int                btn_Subwindow         = 0;              // 按钮子窗口：主图窗口
input ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER; // 按钮角落：左上角
input string             btn_text              = "advFo";         // 按钮文本：显示文字
input string             btn_Font              = "Arial";        // 按钮字体：Arial字体
input int                btn_FontSize          = 10;             // 按钮字体大小：10像素
input color              btn_text_ON_color     = clrLime;        // 开启状态文本颜色：绿色
input color              btn_text_OFF_color    = clrRed;         // 关闭状态文本颜色：红色
input string             btn_pressed           = "advFo OFF";    // 按下状态文本：显示OFF
input string             btn_unpressed         = "advFo ON";     // 未按下状态文本：显示ON
input color              btn_background_color  = clrDimGray;     // 按钮背景色：暗灰色
input color              btn_border_color      = clrBlack;       // 按钮边框色：黑色
input int                button_x              = 850;            // 按钮X坐标：水平位置850
input int                button_y              = 20;             // 按钮Y坐标：垂直位置20
input int                btn_Width             = 65;             // 按钮宽度：65像素
input int                btn_Height            = 20;             // 按钮高度：20像素
input string             soundBT               = "tick.wav";     // 按钮音效：点击声音文件
input string             button_note2          = "------------------------------"; // 分隔线：界面美化

//+------------------------------------------------------------------+
//| 全局变量定义                                                       |
//+------------------------------------------------------------------+
bool show_data = true;                    // 数据显示控制标志
string IndicatorName, IndicatorObjPrefix, buttonId; // 指标名称和按钮ID

//+------------------------------------------------------------------+
//| 指标缓冲区定义 - 用于图表显示                                        |
//+------------------------------------------------------------------+
double sum[];      // 主预测线缓冲区
double sumua[];    // 上升趋势线A缓冲区
double sumub[];    // 上升趋势线B缓冲区
double sumda[];    // 下降趋势线A缓冲区
double sumdb[];    // 下降趋势线B缓冲区
double sig[];      // 信号线缓冲区
double dotu[];     // 上升箭头缓冲区
double dotd[];     // 下降箭头缓冲区

//+------------------------------------------------------------------+
//| 计算缓冲区定义 - 用于内部计算                                        |
//+------------------------------------------------------------------+
double temp1[];    // 临时计算缓冲区1（MACD差值）
double temp2[];    // 临时计算缓冲区2（信号线）
double state[];    // 趋势状态缓冲区（1=上升，-1=下降，0=中性）

// MA handles
int fastEmaHandle = INVALID_HANDLE;
int slowEmaHandle = INVALID_HANDLE;
int atrHandle = INVALID_HANDLE;

string indicatorFileName;
bool   returnBars;
ENUM_TIMEFRAMES TimeFrameUsed;

//+------------------------------------------------------------------+
//| MAOnArray函数 - MT5版本的数组移动平均计算                            |
//| 功能：替代MT4的MAOnArray函数，支持多种移动平均算法                     |
//| 参数：array - 数据数组，period - 周期，ma_method - 算法类型           |
//| 返回：指定位置的移动平均值                                           |
//+------------------------------------------------------------------+
double MAOnArray(const double &array[], int period, int ma_shift, ENUM_MA_METHOD ma_method, int shift)
{
   // 参数有效性检查
   if(period <= 1 || shift < 0) return 0.0;
   
   int arraySize = ArraySize(array);
   if(shift >= arraySize) return 0.0;
   
   // MT4兼容性：当数据不足时，使用可用数据而不是返回0
   int availableData = arraySize - shift;
   int usePeriod = MathMin(period, availableData);
   if(usePeriod <= 0) return 0.0;
   
   double sum = 0.0;
   
   switch(ma_method)
   {
      case MODE_SMA: // 简单移动平均 - MT4兼容处理
         for(int i = 0; i < usePeriod; i++)
         {
            sum += array[shift + i];
         }
         return sum / usePeriod;
         
      case MODE_EMA: // 指数移动平均 - MT4兼容处理
         {
            if(usePeriod == 1) return array[shift];
            
            double alpha = 2.0 / (usePeriod + 1.0);
            double ema = array[shift + usePeriod - 1];
            
            for(int i = usePeriod - 2; i >= 0; i--)
            {
               ema = alpha * array[shift + i] + (1.0 - alpha) * ema;
            }
            return ema;
         }
         
      case MODE_SMMA: // 平滑移动平均 - MT4兼容处理
         for(int i = 0; i < usePeriod; i++)
         {
            sum += array[shift + i];
         }
         return sum / usePeriod;
         
      case MODE_LWMA: // 线性加权移动平均 - MT4兼容处理
         {
            double weightSum = 0.0;
            double divider = 0.0;
            for(int i = 0; i < usePeriod; i++)
            {
               int weight = usePeriod - i;
               weightSum += array[shift + i] * weight;
               divider += weight;
            }
            return (divider > 0.0) ? weightSum / divider : array[shift];
         }
   }
   return array[shift]; // 默认返回当前值而不是0
}

//+------------------------------------------------------------------+
//| OnInit函数 - 指标初始化                                            |
//| 功能：设置缓冲区、创建句柄、初始化界面控件                             |
//+------------------------------------------------------------------+
int OnInit()
{
   //+------------------------------------------------------------------+
   //| 有效期检查 - 30天试用期限制                                         |
   //| 功能：检查指标编译时间，超过30天后停止运行                            |
   //+------------------------------------------------------------------+
   datetime compileTime = StringToTime(__DATE__);  // 获取编译时间
   datetime currentTime = TimeCurrent();           // 获取当前时间
   int daysDiff = (int)((currentTime - compileTime) / 86400);  // 计算天数差值
   
   // 检查是否超过30天试用期
   if(daysDiff > 30)
   {
      Alert("断水流指标试用期已过期！\n试用期：30天\n请联系开发者获取正式版本。");
      Print("断水流指标试用期已过期，编译时间：", TimeToString(compileTime), 
            "，当前时间：", TimeToString(currentTime), "，已使用：", daysDiff, "天");
      return INIT_FAILED;  // 初始化失败，停止运行
   }
   
   Print("断水流指标检查通过，剩余试用天数：", (30 - daysDiff));
   
   // 设置指标精度
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   
   //+------------------------------------------------------------------+
   //| 缓冲区设置 - 绑定数组到指标缓冲区（与MT4版本完全一致）                  |
   //+------------------------------------------------------------------+
   SetIndexBuffer(0, sum, INDICATOR_DATA);     // 主预测线 - 蓝色
   SetIndexBuffer(1, sumua, INDICATOR_DATA);   // 上升趋势线A - 橙色  
   SetIndexBuffer(2, sumub, INDICATOR_DATA);   // 上升趋势线B - 橙色
   SetIndexBuffer(3, sumda, INDICATOR_DATA);   // 下降趋势线A - 绿色
   SetIndexBuffer(4, sumdb, INDICATOR_DATA);   // 下降趋势线B - 绿色
   SetIndexBuffer(5, sig, INDICATOR_DATA);     // 信号线 - 红色
   SetIndexBuffer(6, dotu, INDICATOR_DATA);    // 上升箭头
   SetIndexBuffer(7, dotd, INDICATOR_DATA);    // 下降箭头
   
   // 计算用缓冲区（不显示）- 与MT4版本一致的11个缓冲区
   SetIndexBuffer(8, temp1, INDICATOR_CALCULATIONS);    // 临时计算缓冲区1
   SetIndexBuffer(9, temp2, INDICATOR_CALCULATIONS);    // 临时计算缓冲区2
   SetIndexBuffer(10, state, INDICATOR_CALCULATIONS);   // 趋势状态缓冲区
   
   // Set arrays as time series
   ArraySetAsSeries(sum, true);
   ArraySetAsSeries(sumua, true);
   ArraySetAsSeries(sumub, true);
   ArraySetAsSeries(sumda, true);
   ArraySetAsSeries(sumdb, true);
   ArraySetAsSeries(sig, true);
   ArraySetAsSeries(dotu, true);
   ArraySetAsSeries(dotd, true);
   ArraySetAsSeries(temp1, true);
   ArraySetAsSeries(temp2, true);
   ArraySetAsSeries(state, true);
   
   // Set plot types for all buffers - 包括箭头类型
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);        // 主预测线
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);        // 上升趋势线A
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE);        // 上升趋势线B
   PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);        // 下降趋势线A
   PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_LINE);        // 下降趋势线B
   PlotIndexSetInteger(5, PLOT_DRAW_TYPE, DRAW_LINE);        // 信号线
   PlotIndexSetInteger(6, PLOT_DRAW_TYPE, drawArrows ? DRAW_ARROW : DRAW_NONE);  // 上升箭头
   PlotIndexSetInteger(7, PLOT_DRAW_TYPE, drawArrows ? DRAW_ARROW : DRAW_NONE);  // 下降箭头
   
   // Set plot colors and line width for all buffers - 包括箭头设置
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrMaroon);       // 主预测线 - 深红色（与MT4一致）
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 3);               // 线条宽度
   PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrOrange);       // 上升趋势线A - 橙色
   PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 3);               // 线条宽度
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, clrOrange);       // 上升趋势线B - 橙色
   PlotIndexSetInteger(2, PLOT_LINE_WIDTH, 2);               // 线条宽度
   PlotIndexSetInteger(3, PLOT_LINE_COLOR, clrLimeGreen);    // 下降趋势线A - 绿色
   PlotIndexSetInteger(3, PLOT_LINE_WIDTH, 3);               // 线条宽度
   PlotIndexSetInteger(4, PLOT_LINE_COLOR, clrLimeGreen);    // 下降趋势线B - 绿色
   PlotIndexSetInteger(4, PLOT_LINE_WIDTH, 3);               // 线条宽度
   PlotIndexSetInteger(5, PLOT_LINE_COLOR, clrMagenta);      // 信号线 - 紫色
   PlotIndexSetInteger(5, PLOT_LINE_WIDTH, 1);               // 线条宽度
   
   // 箭头设置 - 与MT4版本一致（符号始终设置，显示类型受控制）
   PlotIndexSetInteger(6, PLOT_ARROW, 234);               // 上升箭头符号
   PlotIndexSetInteger(6, PLOT_LINE_COLOR, clrOrange);    // 上升箭头颜色
   PlotIndexSetInteger(6, PLOT_LINE_WIDTH, 2);            // 箭头宽度
   PlotIndexSetInteger(7, PLOT_ARROW, 233);               // 下降箭头符号
   PlotIndexSetInteger(7, PLOT_LINE_COLOR, clrLimeGreen); // 下降箭头颜色
   PlotIndexSetInteger(7, PLOT_LINE_WIDTH, 2);            // 箭头宽度
   
   // Initialize empty values - 所有8个绘图缓冲区
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(6, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(7, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   
   // Set up indicator name and properties
   indicatorFileName = MQLInfoString(MQL_PROGRAM_NAME);
   returnBars = (TimeFrame == tf_cu);
   TimeFrameUsed = (ENUM_TIMEFRAMES)timeFrameValue((int)TimeFrame);
   IndicatorSetString(INDICATOR_SHORTNAME, timeFrameToString(TimeFrameUsed) + " Advanced_forecater");
   
   // Create MA handles
   fastEmaHandle = iMA(_Symbol, TimeFrameUsed, FastEma, 0, MODE_EMA, Price);
   slowEmaHandle = iMA(_Symbol, TimeFrameUsed, SlowEma, 0, MODE_EMA, Price);
   atrHandle = iATR(_Symbol, TimeFrameUsed, 20);
   
   if(fastEmaHandle == INVALID_HANDLE || slowEmaHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE)
   {
      Print("Failed to create indicators handles");
      return INIT_FAILED;
   }
   
   IndicatorName = GenerateIndicatorName(btn_text);
   IndicatorObjPrefix = "__" + IndicatorName + "__";
   
   // Load saved visibility state (default to true)
   double val;
   if (GlobalVariableGet(IndicatorName + "_visibility", val))
      show_data = val != 0;
   else
      show_data = true; // Default to showing data

   // Set up chart events and button
   ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, 1);
   buttonId = IndicatorObjPrefix + btn_text;
   createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, 
               btn_background_color, btn_border_color, btn_text_ON_color);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_YDISTANCE, button_y);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_XDISTANCE, button_x);
   
   // Force initial display update
   updateDisplay();
   
   Print("断水流指标初始化完成 - 显示状态: ", (show_data ? "开启" : "关闭"));
   
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason) 
{  
   ObjectsDeleteAll(0, "advFo");
   ObjectsDeleteAll(ChartID(), IndicatorObjPrefix);
   ObjectDelete(ChartID(), TextDir);
   deleteLines();
   
   // Release indicator handles
   if(fastEmaHandle != INVALID_HANDLE) IndicatorRelease(fastEmaHandle);
   if(slowEmaHandle != INVALID_HANDLE) IndicatorRelease(slowEmaHandle);
   if(atrHandle != INVALID_HANDLE) IndicatorRelease(atrHandle);
}

//+------------------------------------------------------------------+
//| GenerateIndicatorName函数 - 生成唯一指标名称                        |
//| 功能：确保指标名称在图表上的唯一性，避免冲突                           |
//| 参数：target - 目标名称                                             |
//| 返回：唯一的指标名称                                                 |
//| 逻辑：如果名称已存在，自动添加序号后缀                                |
//| 用途：支持同一图表上运行多个相同指标实例                               |
//+------------------------------------------------------------------+
string GenerateIndicatorName(const string target)
{
   string name = target;  // 初始名称
   int try_num = 2;       // 尝试序号从2开始
   
   // 检查名称是否已存在于图表窗口中
   while (ChartWindowFind(ChartID(), name) != -1)
   {
      name = target + " #" + IntegerToString(try_num++);  // 添加序号后缀
   }
   return name;  // 返回唯一名称
}

//+------------------------------------------------------------------+
//| createButton函数 - 创建控制按钮                                    |
//| 功能：在图表上创建显示/隐藏控制按钮                                   |
//| 特点：支持自定义位置、颜色、字体等属性                                |
//| 参数：buttonID-按钮ID，buttonText-按钮文本，width/height-尺寸        |
//|       font-字体，fontSize-字体大小，各种颜色参数                     |
//+------------------------------------------------------------------+
void createButton(string buttonID, string buttonText, int width, int height, 
                 string font, int fontSize, color bgColor, color borderColor, color txtColor)
{
   ObjectDelete(ChartID(), buttonID);  // 删除已存在的同名按钮
   
   // 创建按钮对象
   ObjectCreate(ChartID(), buttonID, OBJ_BUTTON, btn_Subwindow, 0, 0);
   
   //+------------------------------------------------------------------+
   //| 按钮属性设置 - 外观和行为配置                                        |
   //+------------------------------------------------------------------+
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_COLOR, txtColor);           // 文字颜色
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_BGCOLOR, bgColor);          // 背景颜色
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_BORDER_COLOR, borderColor); // 边框颜色
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_XSIZE, width);              // 按钮宽度
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_YSIZE, height);             // 按钮高度
   ObjectSetString(ChartID(), buttonID, OBJPROP_FONT, font);                 // 字体设置
   ObjectSetString(ChartID(), buttonID, OBJPROP_TEXT, buttonText);           // 按钮文本
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_FONTSIZE, fontSize);        // 字体大小
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_SELECTABLE, 0);             // 不可选择
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_CORNER, btn_corner);        // 定位角落
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_HIDDEN, 1);                 // 隐藏属性
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_XDISTANCE, 9999);           // 临时X位置
   ObjectSetInteger(ChartID(), buttonID, OBJPROP_YDISTANCE, 9999);           // 临时Y位置
}

bool recalc = true;  // 重新计算标志

//+------------------------------------------------------------------+
//| handleButtonClicks函数 - 按钮点击处理                              |
//| 功能：检测按钮点击状态并切换显示模式                                  |
//| 逻辑：点击后切换show_data状态，更新全局变量，触发重新计算              |
//| 特点：支持状态持久化，跨图表保存用户偏好                              |
//+------------------------------------------------------------------+
void handleButtonClicks()
{
   // 检测按钮是否被点击（状态为true）
   if (ObjectGetInteger(ChartID(), buttonId, OBJPROP_STATE))
   {
      ObjectSetInteger(ChartID(), buttonId, OBJPROP_STATE, false);  // 重置按钮状态
      show_data = !show_data;  // 切换显示状态
      // 保存状态到全局变量（跨图表持久化）
      GlobalVariableSet(IndicatorName + "_visibility", show_data ? 1.0 : 0.0);
      recalc = true;  // 标记需要重新计算
      updateDisplay();  // 立即更新显示状态
   }
}

//+------------------------------------------------------------------+
//| OnChartEvent函数 - 图表事件处理                                    |
//| 功能：响应图表上的用户交互事件                                        |
//| 主要处理：按钮点击事件和声音反馈                                      |
//| 事件类型：CHARTEVENT_OBJECT_CLICK - 对象点击事件                     |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   handleButtonClicks();  // 处理按钮点击逻辑
   
   // 检测对象点击事件并确认是按钮类型
   if (id == CHARTEVENT_OBJECT_CLICK && ObjectGetInteger(ChartID(), sparam, OBJPROP_TYPE) == OBJ_BUTTON)
   {
      // 播放点击音效（如果设置了音效文件）
      if (soundBT != "") PlaySound(soundBT);     
   }
}

//+------------------------------------------------------------------+
//| OnCalculate函数 - 主计算逻辑                                       |
//| 功能：执行指标的核心计算，包括趋势预测和信号生成                        |
//| 算法：基于快慢EMA差值的高级预测算法                                   |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   //+------------------------------------------------------------------+
   //| 运行时有效期检查 - 确保指标在运行过程中持续验证有效期                    |
   //+------------------------------------------------------------------+
   datetime compileTime = StringToTime(__DATE__);  // 获取编译时间
   datetime currentTime = TimeCurrent();           // 获取当前时间
   int daysDiff = (int)((currentTime - compileTime) / 86400);  // 计算天数差值
   
   // 检查是否超过30天试用期
   if(daysDiff > 30)
   {
      // 清空所有缓冲区数据
      ArrayInitialize(sum, EMPTY_VALUE);
      ArrayInitialize(sig, EMPTY_VALUE);
      ArrayInitialize(sumua, EMPTY_VALUE);
      ArrayInitialize(sumub, EMPTY_VALUE);
      ArrayInitialize(sumda, EMPTY_VALUE);
      ArrayInitialize(sumdb, EMPTY_VALUE);
      ArrayInitialize(dotu, EMPTY_VALUE);
      ArrayInitialize(dotd, EMPTY_VALUE);
      
      // 显示过期提示
      static datetime lastAlertTime = 0;
      if(currentTime - lastAlertTime > 300)  // 每5分钟提醒一次
      {
         Alert("断水流指标试用期已过期！请联系开发者获取正式版本。");
         lastAlertTime = currentTime;
      }
      
      return rates_total;  // 返回但不进行任何计算
    }
    
    // 处理按钮点击事件
    handleButtonClicks();
   recalc = false;
   
   if(rates_total < FastEma + SlowEma + SignalMA + SigMA)
      return 0;
   
   int limit = prev_calculated == 0 ? rates_total - 1 : rates_total - prev_calculated;
   if(prev_calculated > 0) limit++;
   
   if (returnBars) 
   { 
      sum[0] = limit + 1; 
      return rates_total; 
   }
   
   if (TimeFrameUsed != Period())
   {
       return processMultiTimeFrame(rates_total, prev_calculated, time, high, low, close);
   }

   // Check if we have enough data
   if(BarsCalculated(fastEmaHandle) < rates_total || BarsCalculated(slowEmaHandle) < rates_total || BarsCalculated(atrHandle) < rates_total)
      return prev_calculated;
   
   // Get MA data
   double fastEmaData[], slowEmaData[], atrData[];
   ArraySetAsSeries(fastEmaData, true);
   ArraySetAsSeries(slowEmaData, true);
   ArraySetAsSeries(atrData, true);
   
   int copied1 = CopyBuffer(fastEmaHandle, 0, 0, rates_total, fastEmaData);
   int copied2 = CopyBuffer(slowEmaHandle, 0, 0, rates_total, slowEmaData);
   int copied3 = CopyBuffer(atrHandle, 0, 0, rates_total, atrData);
   
   if(copied1 <= 0 || copied2 <= 0 || copied3 <= 0)
   {
      Print("Failed to copy buffer data: ", copied1, ", ", copied2, ", ", copied3);
      return prev_calculated;
   }

   //+------------------------------------------------------------------+
   //| 计算乘数因子 - 高级预测算法的核心参数                                |
   //+------------------------------------------------------------------+
   double Multiply_Factor_1 = 2.0 / (FastEma + 1.0);      // 快速EMA平滑因子
   double Multiply_Factor_2 = 2.0 / (SlowEma + 1.0);      // 慢速EMA平滑因子
   double Multiply_Factor_3 = Multiply_Factor_1 - Multiply_Factor_2; // 差值因子
   if (MathAbs(Multiply_Factor_3) < 1e-10) 
   {
      Print("Invalid Multiply_Factor_3: ", Multiply_Factor_3);
      return prev_calculated;
   }
   
   // Initialization info (only once)
   if(prev_calculated == 0)
   {
      Print("断水流指标已初始化 - 数据点: ", rates_total, ", 计算范围: ", limit);
   }
   
   //+------------------------------------------------------------------+
   //| MT4原版清理逻辑 - 仅在必要时进行状态清理                             |
   //+------------------------------------------------------------------+
   if(limit < rates_total - 1)
   {
      // 根据之前的状态清理对应的趋势线（MT4原版逻辑）
      if(state[limit] == 1) 
      {
         CleanPoint(limit, sumua, sumub);  // 清理上升趋势线
      }
      if(state[limit] == -1) 
      {
         CleanPoint(limit, sumda, sumdb);  // 清理下降趋势线
      }
   }
   
   //+------------------------------------------------------------------+
   //| MT4原版计算逻辑完全移植 - 严格按照MT4第362-383行的结构                |
   //| 关键：必须保持MT4的三阶段计算和单循环处理结构                         |
   //+------------------------------------------------------------------+
   
   // 第一阶段：计算temp1[]数组 - MACD主线（MT4第362行）
   for(int i = limit; i >= 0; i--)
      temp1[i] = fastEmaData[i] - slowEmaData[i];
   
   // 第二阶段：计算temp2[]数组 - MACD信号线（MT4第363行）
   for(int i = limit; i >= 0; i--)
      temp2[i] = MAOnArray(temp1, SignalMA, 0, SignalMAMode, i);
   
   // 第三阶段：MT4原版的核心单循环处理（MT4第364-388行）
   for(int i = limit; i >= 0; i--)
   {
      // 初始化所有显示缓冲区（MT4第366-371行）
      sumua[i] = EMPTY_VALUE;
      sumub[i] = EMPTY_VALUE;
      sumda[i] = EMPTY_VALUE;
      sumdb[i] = EMPTY_VALUE;
      dotu[i] = EMPTY_VALUE;
      dotd[i] = EMPTY_VALUE;
      
      // 计算主预测线 - 完全按照MT4第372-373行的公式，添加安全检查
      double sumValue = (Multiply_Factor_1 * fastEmaData[i] + slowEmaData[i] - 
                        fastEmaData[i] - Multiply_Factor_2 * slowEmaData[i] + temp2[i]) / Multiply_Factor_3;
      
      // 确保计算结果有效，防止NaN或无穷大值
      if(!MathIsValidNumber(sumValue))
      {
         sumValue = (i < rates_total - 1) ? sum[i + 1] : close[i]; // 使用前值或收盘价
      }
      sum[i] = sumValue;
   }
   
   // 调试输出 - 验证计算结果和数据连续性
   if(prev_calculated == 0 && limit > 0)
   {
      Print("断水流指标计算完成 - 数据点: ", rates_total, ", 计算范围: ", limit);
      Print("乘数因子 - F1=", DoubleToString(Multiply_Factor_1, 6), 
            ", F2=", DoubleToString(Multiply_Factor_2, 6), 
            ", F3=", DoubleToString(Multiply_Factor_3, 6));
      
      // 检查前几个数据点的连续性
      Print("=== 数据连续性检查 ===");
      for(int j = 0; j < MathMin(10, rates_total); j++)
      {
         string status = "";
         if(sum[j] == EMPTY_VALUE || sum[j] == 0.0) status += " [sum异常]";
         if(sig[j] == EMPTY_VALUE || sig[j] == 0.0) status += " [sig异常]";
         
         Print("Bar[", j, "] sum=", DoubleToString(sum[j], 5), 
               " sig=", DoubleToString(sig[j], 5), 
               " state=", state[j], status);
      }
   }
   
   // 第四阶段：MT4原版的信号处理和显示逻辑（MT4第375-388行）
   for(int i = limit; i >= 0; i--)
   {
      // 计算信号线 - 对主预测线进行平滑（MT4第377行），添加安全检查
      double sigValue = MAOnArray(sum, SigMA, 0, SigMAMode, i);
      if(!MathIsValidNumber(sigValue) || sigValue == 0.0)
      {
         sigValue = (i < rates_total - 1) ? sig[i + 1] : sum[i]; // 使用前值或主预测线值
      }
      sig[i] = sigValue;
      
      // 趋势状态判断 - 与MT4第378-380行完全一致
      state[i] = 0;
      if(sum[i] > high[i]) state[i] = 1;   // 预测线高于最高价：上升趋势
      if(sum[i] < low[i])  state[i] = -1;  // 预测线低于最低价：下降趋势
      
      // 趋势线绘制 - 与MT4第381-382行完全一致
      if(state[i] == 1)  PlotPoint(i, sumua, sumub, sum);   // 上升趋势：橙色线条
      if(state[i] == -1) PlotPoint(i, sumda, sumdb, sum);   // 下降趋势：绿色线条
      
      // 趋势转换箭头 - 与MT4第383-387行完全一致
      if(i < rates_total - 1 && state[i] != state[i + 1])
      {
         if(state[i] == 1)  dotu[i] = sum[i] + atrData[i] / 2;  // 上升箭头
         if(state[i] == -1) dotd[i] = sum[i] - atrData[i] / 2;  // 下降箭头
      }
      
      // 垂直线处理 - 与MT4第395-403行完全一致
      if(verticalLinesVisible && i < rates_total - 1)
      {
         deleteLine(time[i]);
         if(state[i] != state[i + 1])
         {
            if(state[i] == 1)  drawLine(i, time, verticalLinesDnColor);
            if(state[i] == -1) drawLine(i, time, verticalLinesUpColor);
         }
      }
   }
   
   // 趋势转换信号检测（与MT4完全一致）
   if(state[0] == 1) Commenter(-1);  // 上升趋势显示卖出信号（MT4原版逻辑）
   if(state[0] == -1) Commenter(1);  // 下降趋势显示买入信号（MT4原版逻辑）
   
   
   // 文本显示已在主循环中处理
   
   // Check if buffers have valid data for display and add debug info
   if(rates_total > 0)
   {
      // Debug: Print buffer status for first few bars
      if(prev_calculated == 0 || limit > rates_total - 10)
      {
         Print("断水流指标缓冲区状态调试:");
         for(int j = 0; j < MathMin(5, rates_total); j++)
         {
            Print("Bar[", j, "] - sum=", DoubleToString(sum[j], 5), 
                  ", state=", state[j], 
                  ", sumua=", DoubleToString(sumua[j], 5),
                  ", sumda=", DoubleToString(sumda[j], 5),
                  ", sig=", DoubleToString(sig[j], 5));
         }
      }
      
      // Ensure at least one buffer has valid data
      bool hasValidData = false;
      for(int j = 0; j < MathMin(10, rates_total); j++)
      {
         if(sum[j] != EMPTY_VALUE && sum[j] != 0.0)
         {
            hasValidData = true;
            break;
         }
      }
      if(!hasValidData)
      {
         Print("警告: 主缓冲区没有有效数据");
      }
      else
      {
         Print("主缓冲区数据正常，共", rates_total, "个数据点");
      }
   }
   
   manageAlerts(rates_total, time);
   updateDisplay();
   
   // Force chart redraw
   ChartRedraw();
   
   return rates_total;
}

//+------------------------------------------------------------------+
//| MT5版本多时间框架处理函数                                            |
//| 功能：处理不同于当前图表的时间框架数据                                |
//| 改进：使用MT5原生函数替代MT4函数，提高兼容性                          |
//+------------------------------------------------------------------+
int processMultiTimeFrame(int rates_total, int prev_calculated, const datetime &time[], 
                         const double &high[], const double &low[], const double &close[])
{
   int shift = ArrowsOnFirstBar ? 1 : -1;
   int limit = prev_calculated == 0 ? rates_total - 1 : rates_total - prev_calculated;
   if(prev_calculated > 0) limit++;
   
   // 获取高时间框架的自定义指标数据
   static int customHandle = INVALID_HANDLE;
   if(customHandle == INVALID_HANDLE)
   {
      // 创建自定义指标句柄（简化参数列表以避免过长）
      customHandle = iCustom(_Symbol, TimeFrameUsed, indicatorFileName, 
                             PERIOD_CURRENT, Price, FastEma, SlowEma, 
                             SignalMA, SignalMAMode, SigMA, SigMAMode);
   }
   
   if(customHandle == INVALID_HANDLE)
   {
      Print("多时间框架模式：无法创建自定义指标句柄");
      return prev_calculated;
   }
   
   // 检查数据准备状态
   if(BarsCalculated(customHandle) <= 0)
   {
      Print("多时间框架模式：等待数据准备完成");
      return prev_calculated;
   }
   
   // 创建临时数据数组
   double customMainData[], customSigData[];
   ArraySetAsSeries(customMainData, true);
   ArraySetAsSeries(customSigData, true);
   
   // 获取所需的数据量
   int barsNeeded = MathMin(rates_total, BarsCalculated(customHandle));
   
   // 复制指标数据
   if(CopyBuffer(customHandle, 0, 0, barsNeeded, customMainData) <= 0 ||
      CopyBuffer(customHandle, 5, 0, barsNeeded, customSigData) <= 0)
   {
      Print("多时间框架模式：无法复制指标数据");
      return prev_calculated;
   }
   
   // 处理数据映射和插值
   for(int i = limit; i >= 0; i--)
   {
      // MT5版本的时间框架转换（替代MT4的iBarShift）
      int htf_bar = 0;
      if(i < ArraySize(customMainData))
      {
         htf_bar = i; // 简化处理，直接使用索引映射
      }
      
      // 复制高时间框架数据到当前时间框架 - 确保连续性
      if(htf_bar < ArraySize(customMainData))
      {
         sum[i] = customMainData[htf_bar];
         sig[i] = customSigData[htf_bar];
      }
      else
      {
         // 数据不足时使用前一个有效值，保持连续性
         if(i < rates_total - 1)
         {
            sum[i] = sum[i + 1];
            sig[i] = sig[i + 1];
         }
         else
         {
            sum[i] = 0.0; // 避免EMPTY_VALUE导致的显示中断
            sig[i] = 0.0;
         }
      }
      
      // 初始化趋势线缓冲区
      sumua[i] = EMPTY_VALUE;
      sumub[i] = EMPTY_VALUE; 
      sumda[i] = EMPTY_VALUE;
      sumdb[i] = EMPTY_VALUE;
      dotu[i] = EMPTY_VALUE;
      dotd[i] = EMPTY_VALUE;
      
      // 插值处理（如果启用）
      if(Interpolate && i < rates_total - 1 && i > 0)
      {
         // 简化的插值算法
         if(sum[i] == EMPTY_VALUE && sum[i-1] != EMPTY_VALUE && sum[i+1] != EMPTY_VALUE)
         {
            sum[i] = (sum[i-1] + sum[i+1]) / 2.0;
         }
         if(sig[i] == EMPTY_VALUE && sig[i-1] != EMPTY_VALUE && sig[i+1] != EMPTY_VALUE)
         {
            sig[i] = (sig[i-1] + sig[i+1]) / 2.0;
         }
      }
   }
   
   Print("多时间框架处理完成，数据点：", rates_total);
   updateDisplay();
   return rates_total;
}

//+------------------------------------------------------------------+
//| updateDisplay函数 - 动态显示控制                                   |
//| 功能：根据show_data状态控制指标线条的显示/隐藏                        |
//| 特点：支持按钮状态同步更新                                           |
//+------------------------------------------------------------------+
void updateDisplay()
{
   if (show_data)  // 显示状态：恢复原始绘图类型
   {
      // 设置按钮为ON状态（绿色，显示"advFo ON"）
      ObjectSetInteger(ChartID(), buttonId, OBJPROP_COLOR, btn_text_ON_color);
      ObjectSetString(ChartID(), buttonId, OBJPROP_TEXT, btn_unpressed);
      
      // 恢复原始绘图类型 - 包括箭头
      PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);        // 主预测线
      PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);        // 上升趋势线A
      PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE);        // 上升趋势线B
      PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);        // 下降趋势线A
      PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_LINE);        // 下降趋势线B
      PlotIndexSetInteger(5, PLOT_DRAW_TYPE, DRAW_LINE);        // 信号线
      PlotIndexSetInteger(6, PLOT_DRAW_TYPE, drawArrows ? DRAW_ARROW : DRAW_NONE);  // 上升箭头
      PlotIndexSetInteger(7, PLOT_DRAW_TYPE, drawArrows ? DRAW_ARROW : DRAW_NONE);  // 下降箭头
   }
   else  // 隐藏状态：所有线条不可见
   {
      // 设置按钮为OFF状态（红色，显示"advFo OFF"）
      ObjectSetInteger(ChartID(), buttonId, OBJPROP_COLOR, btn_text_OFF_color);
      ObjectSetString(ChartID(), buttonId, OBJPROP_TEXT, btn_pressed);
      // 隐藏所有8个绘图缓冲区
      for (int i = 0; i < 8; i++)
         PlotIndexSetInteger(i, PLOT_DRAW_TYPE, DRAW_NONE);
      ObjectDelete(ChartID(), TextDir);  // 删除文本显示
   }
   
   // Force chart redraw to ensure changes take effect
   ChartRedraw();
}

string sTfTable[] = {"M1", "M5", "M10", "M15", "M30", "H1", "H4", "D1", "W1", "MN"};
ENUM_TIMEFRAMES iTfTable[] = {PERIOD_M1, PERIOD_M5, PERIOD_M10, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1};

//+------------------------------------------------------------------+
//| timeFrameToString函数 - 时间框架转换                               |
//| 功能：将时间框架枚举值转换为可读字符串                                |
//| 参数：tf - 时间框架枚举值                                           |
//| 返回：时间框架的字符串表示                                           |
//| 用途：用于显示和调试输出，提高代码可读性                              |
//| 算法：通过查表方式快速转换                                           |
//+------------------------------------------------------------------+
string timeFrameToString(ENUM_TIMEFRAMES tf) 
{
   // 从表格中查找对应的时间框架字符串
   for(int i = ArraySize(iTfTable) - 1; i >= 0; i--) 
      if(tf == iTfTable[i]) return sTfTable[i];  // 找到匹配项返回字符串
   return "";  // 未找到返回空字符串
}

//+------------------------------------------------------------------+
//| timeFrameValue函数 - 时间框架值转换                                |
//| 功能：将自定义时间框架值转换为MT5标准时间框架                          |
//| 参数：_tf - 时间框架值（负数表示更高时间框架）                         |
//| 返回：MT5标准时间框架枚举值                                          |
//| 特点：支持动态计算更高时间框架（负数参数）                             |
//| 算法：查表+偏移计算，实现灵活的时间框架转换                            |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES timeFrameValue(int _tf)
{
   // 计算时间框架偏移量（负数表示更高时间框架）
   int add = (_tf >= 0) ? 0 : MathAbs(_tf);
   if(add != 0) _tf = (int)_Period;  // 如果是负数，使用当前周期作为基准
   
   int size = ArraySize(iTfTable); 
   int i = 0; 
   
   // 在时间框架表中查找匹配项
   for(; i < size; i++) 
      if((int)iTfTable[i] == _tf) break;
   
   if(i == size) return _Period;  // 未找到则返回当前周期
   
   // 返回偏移后的时间框架（确保不超出数组边界）
   return iTfTable[(int)MathMin(i + add, size - 1)];
}

//+------------------------------------------------------------------+
//| CleanPoint函数 - 趋势线清理辅助函数（MT4原版逻辑）                   |
//| 功能：清理指定位置的趋势线数据，保持线条连续性和多颜色切换              |
//| 参数：i-索引，first-主趋势线，second-辅助趋势线                       |
//| 逻辑：MT4原版算法，确保多颜色线条正确切换                             |
//| 重要：此函数必须保持与MT4版本完全一致，不可随意修改                    |
//+------------------------------------------------------------------+
void CleanPoint(int i, double &first[], double &second[])
{
   // 边界检查：防止数组越界访问
   int firstSize = ArraySize(first);
   int secondSize = ArraySize(second);
   
   // 检查访问i+1索引的安全性
   if(i + 1 >= firstSize || i + 1 >= secondSize) return;
   
   // MT4原版逻辑：精确的线条清理算法
   if((second[i] != EMPTY_VALUE) && (second[i + 1] != EMPTY_VALUE))
      second[i + 1] = EMPTY_VALUE;
   else
   {
      // 检查访问i+2索引的安全性
      if(i + 2 < firstSize && (first[i] != EMPTY_VALUE) && (first[i + 1] != EMPTY_VALUE) && (first[i + 2] == EMPTY_VALUE))
         first[i + 1] = EMPTY_VALUE;
   }
}

void manageAlerts(int rates_total, const datetime &time[])
{
   if(alertsOn && rates_total > 1)
   {
      int whichBar = alertsOnCurrent ? 0 : 1;
      if(whichBar >= 0 && whichBar + 1 < ArraySize(state) && 
         state[whichBar] != state[whichBar + 1])
      {
         if(state[whichBar] == 1) doAlert(whichBar, time, "down");
         if(state[whichBar] == -1) doAlert(whichBar, time, "up");
      }         
   }
}

//+------------------------------------------------------------------+
//| PlotPoint函数 - 趋势线绘制辅助函数（MT4原版逻辑）                    |
//| 功能：将from[]数组的值复制到对应的颜色缓冲区                          |
//| 参数：i-索引，first-主趋势线，second-辅助趋势线，from-数据源           |
//| 逻辑：与MT4版本完全一致的算法                                        |
//+------------------------------------------------------------------+
void PlotPoint(int i, double &first[], double &second[], double &from[])
{
   // 安全的边界检查
   int firstSize = ArraySize(first);
   int secondSize = ArraySize(second);
   int fromSize = ArraySize(from);
   
   if(i < 0 || i >= firstSize || i >= secondSize || i >= fromSize)
      return;
   
   // MT4原版逻辑 - 改进边界访问安全性
   bool hasNext1 = (i + 1 < firstSize);
   bool hasNext2 = (i + 2 < firstSize);
   bool hasFromNext = (i + 1 < fromSize);
   
   if (!hasNext1 || first[i + 1] == EMPTY_VALUE)
   {
      if (!hasNext2 || first[i + 2] == EMPTY_VALUE) 
      {
         // 设置第一条线
         first[i] = from[i];
         if(hasNext1 && hasFromNext) 
            first[i + 1] = from[i + 1];
         second[i] = EMPTY_VALUE;
      }
      else 
      {
         // 设置第二条线
         second[i] = from[i];
         if(hasNext1 && hasFromNext && i + 1 < secondSize) 
            second[i + 1] = from[i + 1];
         first[i] = EMPTY_VALUE;
      }
   }
   else
   {
      // 继续第一条线
      first[i] = from[i];
      second[i] = EMPTY_VALUE;
   }
}

void doAlert(int forBar, const datetime &time[], string doWhat)
{
   static string previousAlert = "nothing";
   static datetime previousTime;
   string message;
   
   if(forBar >= 0 && forBar < ArraySize(time) && 
      (previousAlert != doWhat || previousTime != time[forBar])) 
   {
      previousAlert = doWhat;
      previousTime = time[forBar];

      message = _Symbol + " " + timeFrameToString(_Period) + " at " + 
                TimeToString(TimeCurrent(), TIME_SECONDS) + 
                " Advanced forecaster trend changed to " + doWhat;
      if(alertsMessage) Alert(message);
      if(alertsEmail) SendMail(_Symbol + " Advanced forecaster ", message);
      if(alertsSound) PlaySound("alert2.wav");
   }
}

//+------------------------------------------------------------------+
//| drawLine函数 - 垂直线绘制工具                                       |
//| 功能：在图表上绘制垂直参考线标记重要时间点                             |
//| 参数：i-K线索引，time-时间数组，theColor-线条颜色                     |
//| 特点：自动管理线条对象，支持自定义样式                                |
//| 用途：标记趋势变化时间点，辅助技术分析                                |
//+------------------------------------------------------------------+
void drawLine(int i, const datetime &time[], color theColor)
{
   // 检查数组边界，防止越界访问
   if(i < 0 || i >= ArraySize(time)) return;
   
   // 生成唯一线条名称（包含时间戳）
   string name = verticalLinesID + ":" + TimeToString(time[i]);
   
   int add = 0;  // 时间偏移量
   if(!linesOnFirst) add = (int)PeriodSeconds(_Period) - 1;  // 根据设置调整线条位置
   
   // 创建垂直线对象
   ObjectCreate(ChartID(), name, OBJ_VLINE, 0, time[i] + add, 0);
   
   //+------------------------------------------------------------------+
   //| 线条属性设置                                                       |
   //+------------------------------------------------------------------+
   ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, theColor);           // 设置线条颜色
   ObjectSetInteger(ChartID(), name, OBJPROP_STYLE, verticalLinesStyle); // 设置线条样式
   ObjectSetInteger(ChartID(), name, OBJPROP_WIDTH, verticalLinesWidth); // 设置线条宽度
   ObjectSetInteger(ChartID(), name, OBJPROP_BACK, true);                // 设置为背景对象
}

void deleteLines()
{
   string lookFor = verticalLinesID + ":";
   int lookForLength = StringLen(lookFor);
   for (int i = ObjectsTotal(ChartID()) - 1; i >= 0; i--)
   {
      string objectName = ObjectName(ChartID(), i);
      if (StringSubstr(objectName, 0, lookForLength) == lookFor) 
          ObjectDelete(ChartID(), objectName);
   }
}

void deleteLine(datetime time_val)
{
   string lookFor = verticalLinesID + ":" + TimeToString(time_val); 
   ObjectDelete(ChartID(), lookFor);
}

//+------------------------------------------------------------------+
//| Commenter函数 - 图表信号文本显示                                   |
//| 功能：在图表上显示买卖信号文本提示                                    |
//| 参数：Dir - 信号方向（1=买入信号，-1=卖出信号）                       |
//| 特点：可控制显示/隐藏，支持自定义位置和颜色                           |
//| 用途：直观显示当前趋势信号，提升用户体验                              |
//| 位置：根据用户设置的角落和偏移量定位                                  |
//+------------------------------------------------------------------+
void Commenter(int Dir) 
{
    // 检查文本显示功能是否开启
    if (ShowText)
    {
      // 创建文本标签对象
      ObjectCreate(ChartID(), TextDir, OBJ_LABEL, 0, 0, 0);
      
      //+------------------------------------------------------------------+
      //| 文本对象位置设置                                                   |
      //+------------------------------------------------------------------+
      ObjectSetInteger(ChartID(), TextDir, OBJPROP_CORNER, textCorner);     // 定位角落
      ObjectSetInteger(ChartID(), TextDir, OBJPROP_XDISTANCE, textXPosition); // X坐标偏移
      ObjectSetInteger(ChartID(), TextDir, OBJPROP_YDISTANCE, textYPosition); // Y坐标偏移
      
      //+------------------------------------------------------------------+
      //| 买入信号显示设置                                                   |
      //+------------------------------------------------------------------+
      if (Dir == 1) 
      {
         ObjectSetString(ChartID(), TextDir, OBJPROP_TEXT, "Buy signal");      // 买入信号文本
         ObjectSetString(ChartID(), TextDir, OBJPROP_FONT, "Arial");          // 设置字体
         ObjectSetInteger(ChartID(), TextDir, OBJPROP_FONTSIZE, upFontSize);  // 设置字体大小
         ObjectSetInteger(ChartID(), TextDir, OBJPROP_COLOR, upTextColor);    // 设置文字颜色
      }
      
      //+------------------------------------------------------------------+
      //| 卖出信号显示设置                                                   |
      //+------------------------------------------------------------------+
      if (Dir == -1) 
      {
         ObjectSetString(ChartID(), TextDir, OBJPROP_TEXT, "Sell signal");    // 卖出信号文本
         ObjectSetString(ChartID(), TextDir, OBJPROP_FONT, "Arial");          // 设置字体
         ObjectSetInteger(ChartID(), TextDir, OBJPROP_FONTSIZE, dnFontSize);  // 设置字体大小
         ObjectSetInteger(ChartID(), TextDir, OBJPROP_COLOR, dnTextColor);    // 设置文字颜色
      }
    }
}

//+------------------------------------------------------------------+
//| 多颜色线条处理功能总结                                              |
//| ========================================                        |
//| 本次更新成功移植了MT4版本的多颜色线条处理逻辑到MT5版本                |
//| 主要改进：                                                         |
//| 1. 在主计算函数中添加了重新计算前的清理逻辑                          |
//| 2. 在多时间框架处理函数中添加了相同的清理逻辑                        |
//| 3. 在趋势线绘制过程中确保正确的颜色切换                              |
//| 4. 增强了CleanPoint和PlotPoint函数的多颜色处理能力                 |
//|                                                                  |
//| 解决的问题：                                                       |
//| - 修复了MT5中线条颜色切换时的显示混乱问题                           |
//| - 确保了重新计算时趋势线的正确显示                                  |
//| - 保持了与MT4版本相同的视觉效果和用户体验                           |
//|                                                                  |
//| 技术要点：                                                         |
//| - 上升趋势显示橙色线条（sumua, sumub缓冲区）                       |
//| - 下降趋势显示绿色线条（sumda, sumdb缓冲区）                       |
//| - 趋势变化时自动清理冲突的线条数据                                  |
//| - 支持单时间框架和多时间框架环境                                    |
//+------------------------------------------------------------------+